#include "../../head/mainHead.h"

// 最短作业优先算法(非剥夺式)

void sjf(){
    system("cls");
    //构建到达时间队列
    //将到达时间转化为分钟格式
    arrStrsToMin();
    queueInit();
    // 计算到达时间
    // 先确定执行的进程号，再确定进程执行的开始时间
    boolean isProSel[5] = {0};
    int curTime = arriveTime[exeQueue[1]];
    for(int i = 0; i < 5; i++){ // i: 代表exeQueue队列下标
        if(i){
            startTime[exeQueue[i]] = curTime;
            endTime[exeQueue[i]] = curTime + p[exeQueue[i]].Tr;
        }
        if(i == 4){     //所有进程执行完毕，无下一个进程
            break;
        }else{
            // 确认下一个执行进程的进程号
            if(i == 3){ //如果是倒数第二个进程执行完，则直接确定是剩下的那个进程
                exeQueue[i + 1] = 10 - exeQueue[1] - exeQueue[2] - exeQueue[3];
                isProSel[exeQueue[i + 1]] = 1;
                // 更新当前时间
                if(endTime[exeQueue[i]] > arriveTime[exeQueue[i + 1]]){
                    curTime = endTime[exeQueue[i]];
                }else{
                    curTime = arriveTime[exeQueue[i + 1]];
                }  
            }else{  //选取当前已到达，未执行
                boolean hasSel = 0;
                for(int x = 1; x < 5; x++){ // x代表queue[]下标
                    if(isProSel[queue[x]]){ //被选中，则跳过继续遍历
                        continue;
                    }else if(!hasSel){     //初始化下一个执行的进程序号
                        exeQueue[i + 1] = queue[x];  
                        hasSel = 1;
                        
                    }else{
                        if(arriveTime[queue[x]] > curTime || 
                                p[queue[x]].Tr > p[exeQueue[i + 1]].Tr){
                            continue;
                        }else{
                            exeQueue[i + 1] = queue[x]; 
                        }
                    }
                    // 更新当前时间
                    if(i && endTime[exeQueue[i]] > arriveTime[exeQueue[i + 1]]){
                        curTime = endTime[exeQueue[i]];
                    }else{
                        curTime = arriveTime[exeQueue[i + 1]];
                    } 
                }
                isProSel[exeQueue[i + 1]] = 1;             
            }
        }
    }

    // 输出进程执行先后顺序
    exeOrderPrint();
    // 输出进程到达时间
    taPrint();
    // 将开始时间分钟格式转化为时分格式
    startMinToStrs();
    // 输出开始时间
    tsPrint();
    // 进程运行时间
    trPrint();
    // 将结束时间分钟格式转化为时分格式
    endMinToStrs();
    // 输出结束时间
    tfPrint();

    // 计算周转时间
    calcuTar();
    // 计算带权周转时间
    calcuTTWA();
    // 输出进程周转时间
    cycleTime();
    // 输出带权周转时间
    cycleTimeWithRight();
    // 输出平均周转时间
    avgCycleTime();
    // 输出平均带权周转时间
    avgCycleTimeWithRight();
}